home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / grn / hgraph.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-12  |  11.4 KB  |  382 lines

  1. /*    hgraph.c    1.15    (Berkeley) 86/04/14
  2.  *
  3.  *     This file contains the graphics routines for converting gremlin
  4.  * pictures to troff input.
  5.  */
  6.  
  7. #include "gprint.h"
  8.  
  9.  
  10. #define  MAXVECT    40
  11. #define  pi        3.14159265358979324
  12. #define  twopi        (2.0 * pi)
  13. #define  len(a, b)    sqrt((b.x-a.x) * (b.x-a.x) + (b.y-a.y) * (b.y-a.y))
  14.  
  15.  
  16. extern int style[];    /* line and character styles */
  17. extern int thick[];
  18. extern char *tfont[];
  19. extern int tsize[];
  20. extern int stipple_index[];    /* stipple font index for stipples 1 - 8 */
  21. extern char *stipple;        /* stipple type (cf or ug) */
  22. extern int oldstipmap;        /* use old-style stipple mapping */
  23.  
  24.  
  25. extern double troffscale;    /* imports from main.c */
  26. extern point();
  27. extern int linethickness;
  28. extern int linmod;
  29. extern int brushinvalid;
  30. extern int lastx;
  31. extern int lasty;
  32. extern int lastyline;
  33. extern int ytop;
  34. extern int ybottom;
  35. extern int xleft;
  36. extern int xright;
  37.  
  38.  
  39. /*----------------------------------------------------------------------------*
  40.  | Routine:    HGPrintElt (element_pointer)
  41.  |
  42.  | Results:    examines a picture element and calls the appropriate
  43.  |        routine(s) to print them according to their type.
  44.  |        After the picture is drawn, current position is (lastx, lasty).
  45.  *----------------------------------------------------------------------------*/
  46.  
  47. HGPrintElt(element)
  48. ELT *element;
  49. {
  50.     register POINT *p1;
  51.     register POINT *p2;
  52.     register int length;
  53.     static int didstipple = 1;    /* flag to prevent multipe messages about no */
  54.                 /* stipple font requested from being printed */
  55.     float firstx, firsty;    /* for completing polygons */
  56.  
  57.     if ( !DBNullelt(element) && !Nullpoint((p1 = element->ptlist))) {
  58.                         /* p1 always has first point */
  59.         if (TEXT(element->type)) {
  60.             HGSetFont(element->brushf, element->size);
  61.             HGPutText(element->type, *p1, element->textpt);
  62.         } else {
  63.         if (element->brushf) {        /* if there is a brush, the */
  64.         HGSetBrush(element->brushf);    /* graphics need it set */
  65.         }
  66.             switch (element->type) {
  67.  
  68.                case ARC:    p2 = PTNextPoint(p1);
  69.                 doarc(*p1, *p2, element->size);
  70.                             break;
  71.  
  72.                case CURVE:  tmove(p1);
  73.                 printf("\\D'g");
  74.                             while (!Nullpoint((p1 = PTNextPoint(p1)))) {
  75.                                 dx((double) p1->x);
  76.                                 dy((double) p1->y);
  77.                             }  /* end while */;
  78.                 putchar('\'');
  79.                 cr();
  80.                             break;
  81.  
  82.                case BSPLINE: tmove(p1);
  83.                 printf("\\D'~");
  84.                             while (!Nullpoint((p1 = PTNextPoint(p1)))) {
  85.                                 dx((double) p1->x);
  86.                                 dy((double) p1->y);
  87.                             }  /* end while */;
  88.                 putchar('\'');
  89.                 cr();
  90.                             break;
  91.  
  92.                case BEZIER: tmove(p1);
  93.                 printf("\\D'z");
  94.                             while (!Nullpoint((p1 = PTNextPoint(p1)))) {
  95.                                 dx((double) p1->x);
  96.                                 dy((double) p1->y);
  97.                             }  /* end while */;
  98.                 putchar('\'');
  99.                 cr();
  100.                             break;
  101.  
  102.           case VECTOR:  length = 1;        /* keep track of line length */
  103.                 tmove(p1);       /* so single lines don't get long */
  104.                             while (!Nullpoint((p1 = PTNextPoint(p1)))) {
  105.                 printf("\\D'l");
  106.                                 dx((double) p1->x);
  107.                                 dy((double) p1->y);
  108.                 putchar('\'');
  109.                 if (length++ > MAXVECT) {
  110.                     cr();
  111.                     tmove (p1);
  112.                     length = 1;
  113.                 }
  114.                             }  /* end while */
  115.                 cr();
  116.                             break;
  117.  
  118.          case POLYGON:  tmove(p1);
  119.                 if (stipple) {
  120.                 didstipple = 1;
  121.                 printf(element->brushf ? "\\D'p %d":"\\D'P %d",
  122.                     (element->size > NSTIPPLES ||
  123.                     oldstipmap == FALSE) ? element->size :
  124.                     stipple_index[element->size - 1]);
  125.                 } else {
  126.                 if (didstipple) {
  127.                     error("no stipple for picture");
  128.                     didstipple = 0;
  129.                 }
  130.                 printf("\\D'p 0");
  131.                 }
  132.  
  133.                 firstx = p1->x;
  134.                 firsty = p1->y;
  135.                             while (!Nullpoint((PTNextPoint(p1)))) {
  136.                 p1 = PTNextPoint(p1);
  137.                                 dx((double) p1->x);
  138.                                 dy((double) p1->y);
  139.                             }  /* end while */;
  140.  
  141.                 /* close polygon if not done so by user */
  142.                 if ((firstx != p1->x) || (firsty != p1->y)) {
  143.                 dx((double) firstx);
  144.                 dy((double) firsty);
  145.                 }
  146.  
  147.                 putchar('\'');
  148.                 cr();
  149.                             break;
  150.             }  /* end switch */
  151.         }  /* end else Text */
  152.     }  /* end if */
  153. }  /* end PrintElt */
  154.  
  155.  
  156. /*----------------------------------------------------------------------------*
  157.  | Routine:    HGPutText (justification, position_point, string)
  158.  |
  159.  | Results:    given the justification, a point to position with, and a
  160.  |        string to put, HGPutText first sends the string into a
  161.  |        diversion, moves to the positioning point, then outputs local
  162.  |        vertical and horizontal motions as needed to justify the text.
  163.  |        After all motions are done, the diversion is printed out.
  164.  *----------------------------------------------------------------------------*/
  165.  
  166. HGPutText(justify,pnt,string)
  167. int justify;
  168. POINT pnt;
  169. register char *string;
  170. {
  171.     int savelasty = lasty;        /* vertical motion for text is to be */
  172.                     /*   ignored.  save current y here */
  173.  
  174.     printf(".nr g8 \\n(.d\n");        /* save current vertical position. */
  175.     printf(".ds g9 \"");        /* define string containing the text. */
  176.     while (*string) {                    /* put out the string */
  177.     if (*string == '\\' && *(string+1) == '\\') {    /* one character at a */
  178.         printf("\\\\\\");                /* time replacing //  */
  179.         string++;                    /* by //// to prevent */
  180.     }                        /* interpretation at  */
  181.     printf("%c", *(string++));            /* printout time */
  182.     }
  183.     printf("\n");
  184.     tmove(&pnt);            /* move to positioning point */
  185.     switch (justify) {
  186.                     /* local vertical motions */
  187.                     /* (the numbers here are used to be */
  188.                     /* somewhat compatible with gprint) */
  189.         case CENTLEFT:
  190.         case CENTCENT:
  191.        case CENTRIGHT:    printf("\\v'0.85n'");        /* down half */
  192.             break;
  193.  
  194.      case TOPLEFT:
  195.      case TOPCENT:
  196.         case TOPRIGHT:    printf("\\v'1.7n'");        /* down whole */
  197.     }
  198.  
  199.     switch (justify) {
  200.                     /* local horizontal motions */
  201.      case BOTCENT:
  202.         case CENTCENT:
  203.      case TOPCENT:    printf("\\h-\\w\\*(g9u/2u");    /* back half */
  204.             break;
  205.  
  206.         case BOTRIGHT:
  207.        case CENTRIGHT:
  208.         case TOPRIGHT:    printf("\\h-\\w\\*(g9u");    /* back whole */
  209.     }
  210.  
  211.     printf("\\&\\*(g9\n");    /* now print the text. */
  212.     printf(".sp |\\n(g8u\n");    /* restore vertical position */
  213.     lasty = savelasty;        /* vertical position restored to where it was */
  214.     lastx = xleft;        /*   before text, also horizontal is at left */
  215. } /* end HGPutText */
  216.  
  217.  
  218. /*----------------------------------------------------------------------------*
  219.  | Routine:    doarc (center_point, start_point, angle)
  220.  |
  221.  | Results:    produces either drawarc command or a drawcircle command
  222.  |        depending on the angle needed to draw through.
  223.  *----------------------------------------------------------------------------*/
  224.  
  225. doarc (cp, sp, angle)
  226. POINT cp;
  227. POINT sp;
  228. int angle;
  229. {
  230.     double radius = len(cp, sp);
  231.     double radians;
  232.  
  233.  
  234.     if (angle) {        /* arc with angle */
  235.         tmove (&sp);        /* starting point first */
  236.         printf("\\D'a");
  237.         dx((double) cp.x);        /* move to center */
  238.         dy((double) cp.y);
  239.  
  240.         radians = acos((sp.x - cp.x) / radius);      /* angle of ending */
  241.         if (cp.y - sp.y < 0.0)             /* point calculated */
  242.         radians = twopi - radians;         /* from start point */
  243.         radians += ((double) angle) * (pi / 180.0);      /* and arc's angle */
  244.         if (radians > twopi) radians -= twopi;
  245.  
  246.         dx(cp.x + cos(radians) * radius);    /* move to ending point */
  247.         dy(cp.y - sin(radians) * radius);
  248.  
  249.     } else {        /* a full circle (angle == 0) */
  250.         cp.x -= radius;
  251.         tmove(&cp);            /* move to the left point first */
  252.                     /* draw circle with given diameter */
  253.         printf("\\D'c %du", (int) ((radius + radius) * troffscale));
  254.     }
  255.     putchar('\'');        /* finish the command */
  256.     cr();
  257. }
  258.  
  259.  
  260. /*----------------------------------------------------------------------------*
  261.  | Routine:    HGSetFont (font_number, Point_size)
  262.  |
  263.  | Results:    ALWAYS outputs a .ft and .ps directive to troff.  This is
  264.  |        done because someone may change stuff inside a text string.
  265.  *----------------------------------------------------------------------------*/
  266.  
  267. HGSetFont(font, size)
  268. int font, size;
  269. {
  270.     printf(".ft %s\n.ps %d\n", tfont[font-1], tsize[size-1]);
  271. }
  272.  
  273.  
  274. /*----------------------------------------------------------------------------*
  275.  | Routine:    HGSetBrush (line_mode)
  276.  |
  277.  | Results:    generates the troff commands to set up the line width and
  278.  |        style of subsequent lines.  Does nothing if no change is needed.
  279.  |
  280.  | Side Efct:    sets "linmode" and "linethicknes"
  281.  *----------------------------------------------------------------------------*/
  282.  
  283. HGSetBrush(mode)
  284. int mode;
  285. {
  286.     register int printed = 0;
  287.  
  288.     if ((linmod != style[--mode]) || brushinvalid) {
  289.     printf ("\\D's %du'", linmod = style[mode]);
  290.     printed = 1;
  291.     }
  292.     if ((linethickness != thick[mode]) || brushinvalid) {
  293.     printf ("\\D't %du'", linethickness = thick[mode]);
  294.     printed = 1;
  295.     }
  296.     if (printed)
  297.     cr();
  298.     brushinvalid = 0;
  299. }
  300.  
  301.  
  302. /*----------------------------------------------------------------------------*
  303.  | Routine:    dx (x_destination)
  304.  |
  305.  | Results:    scales and outputs a number for delta x (with a leading space)
  306.  |        given "lastx" and x_destination.
  307.  |
  308.  | Side Efct:    resets "lastx" to x_destination.
  309.  *----------------------------------------------------------------------------*/
  310.  
  311. dx(x)
  312. double x;
  313. {
  314.     register int ix = (int) (x * troffscale);
  315.  
  316.     printf(" %du", ix - lastx);
  317.     lastx = ix;
  318. }
  319.  
  320.  
  321. /*----------------------------------------------------------------------------*
  322.  | Routine:    dy (y_destination)
  323.  |
  324.  | Results:    scales and outputs a number for delta y (with a leading space)
  325.  |        given "lastyline" and y_destination.
  326.  |
  327.  | Side Efct:    resets "lastyline" to y_destination.  Since "line" vertical
  328.  |        motions don't affect "page" ones, "lasty" isn't updated.
  329.  *----------------------------------------------------------------------------*/
  330.  
  331. dy(y)
  332. double y;
  333. {
  334.     register int iy = (int) (y * troffscale);
  335.  
  336.     printf(" %du", iy - lastyline);
  337.     lastyline = iy;
  338. }
  339.  
  340.  
  341. /*----------------------------------------------------------------------------*
  342.  | Routine:    tmove (point_pointer)
  343.  |
  344.  | Results:    produces horizontal and vertical moves for troff given the
  345.  |        pointer of a point to move to and knowing the current position.
  346.  |        Also puts out a horizontal move to start the line.
  347.  *----------------------------------------------------------------------------*/
  348.  
  349. tmove(ptr)
  350. POINT *ptr;
  351. {
  352.     register int ix = (int) (ptr->x * troffscale);
  353.     register int iy = (int) (ptr->y * troffscale);
  354.     register int dx;
  355.     register int dy;
  356.  
  357.     if (dy = iy - lasty) {
  358.     printf(".sp %du\n", dy);
  359.     }
  360.     lastyline = lasty = iy;        /* lasty is always set to current */
  361.     if (dx = ix - lastx) {
  362.     printf("\\h'%du'", dx);
  363.     lastx = ix;
  364.     }
  365. }
  366.  
  367.  
  368. /*----------------------------------------------------------------------------*
  369.  | Routine:    cr ( )
  370.  |
  371.  | Results:    Ends off an input line.  ".sp -1" is also added to counteract
  372.  |        the vertical move done at the end of text lines.
  373.  |
  374.  | Side Efct:    sets "lastx" to "xleft" for troff's return to left margin
  375.  *----------------------------------------------------------------------------*/
  376.  
  377. cr()
  378. {
  379.     printf("\n.sp -1\n");
  380.     lastx = xleft;
  381. }
  382.